package com.dream.common;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.persistence.Entity;
import javax.persistence.Table;

import net.sf.json.JSON;
import net.sf.json.JSONObject;

import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.hibernate.transform.Transformers;
import org.hibernate.type.Type;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.stereotype.Component;

import com.hxtt.a.c;
import com.hxtt.b.k;
import com.hxtt.concurrent.q;
import com.hxtt.global.s;

@Component("super")
@SuppressWarnings("all")
public class Super<T> extends SuperDao<T>{

	@Autowired
	private SessionFactory sessionFactory;
	
	public void createTableBySQL(String sql){
		this.sessionFactory.getCurrentSession().createSQLQuery(sql).executeUpdate();
	}
	
	public List getListByTableName(String tableName,Object[] params,String sqlCondition,int start,int limit){
		Class<?> claz = ClassUtil.getClass(ClassUtil.getClassNameByTableName(tableName));
		Map<String, Type> map = ClassUtil.getClassHeibernateType(claz.getName());
		StringBuffer sql = new StringBuffer();
		
		sql.append("select ");
		Set<String> keySet = map.keySet();
		int num = 0;
		
		for(String key:keySet){
			if((num + 1) == keySet.size()){
				sql.append("t."+key);
			}else{
				sql.append("t."+key+",");
			}
			num++;
		}
		
		sql.append(" from ");
		sql.append(FreemakerUtil.lowStr(tableName));
		sql.append(" t  join ( select table_id from ");
		sql.append(FreemakerUtil.lowStr(tableName));
		sql.append(" s  ");
		
		if(!"".equals(sqlCondition)){
			sql.append(" where ").append("  s.table_id in ( ").append(sqlCondition).append(")");
		}
		
		if(start != 0 || limit != 0){
			sql.append(" limit ?,? ");
		}
		
		sql.append(" ) b on b.table_id = t.table_id ");
		
		
		SQLQuery  query = this.sessionFactory.getCurrentSession().createSQLQuery(sql.toString());
		query = addSQLQueryParams(claz, query);
		
		for(int i = 0;i < params.length;i++){
			query.setParameter(i, params[i]);
		}
		
		if(start != 0 || limit != 0){
			query.setParameter(params.length, start);
			query.setParameter(params.length+1, limit);
		}
		
		return query.list();
	}
	public int getListCountByTableName(String tableName,Object[] params,String sqlCondition,int start,int limit){
		
		StringBuffer sql = new StringBuffer();
		
		sql.append("select count(table_id) from ");
		sql.append(FreemakerUtil.lowStr(tableName));
		sql.append(" s ");
		
		if(!"".equals(sqlCondition)){
			sql.append(" where ").append("  s.table_id in ( ").append(sqlCondition).append(")");
		}
		
		if(start != 0 || limit != 0){
			sql.append(" limit ?,? ");
		}
		
		Class<?> claz = ClassUtil.getClass(ClassUtil.getClassNameByTableName(tableName));
		SQLQuery  query = this.sessionFactory.getCurrentSession().createSQLQuery(sql.toString());
		
		for(int i = 0;i < params.length;i++){
			query.setParameter(i, params[i]);
		}
		
		if(start != 0 || limit != 0){
			query.setParameter(params.length, start);
			query.setParameter(params.length+1, limit);
		}
		
		return Integer.valueOf(query.uniqueResult().toString());
	}
	public int addSql(String tableName,JSONObject params){
		Class<?> claz = ClassUtil.getClass(ClassUtil.getClassNameByTableName(tableName));
		Map<String, Type> feildMap = ClassUtil.getClassHeibernateType(claz.getName());
		
		Map<String, List<String>> map = parseSQLParamsAndColunm(params, true,feildMap.keySet());
		List<String> paramsList = map.get("paramsList");
		List<String> colunmList = map.get("colunmList");

		StringBuffer sql = new StringBuffer();
		sql.append("insert into ");
		sql.append(FreemakerUtil.lowStr(tableName));
		sql.append("(");
		
		for(int i = 0;i < colunmList.size();i++){
			if((i+1) != colunmList.size()){
				sql.append(colunmList.get(i)).append(",");
			}else{
				sql.append(colunmList.get(i));
			}
		}
		
		sql.append(") values(");
		
		for(int i = 0;i < paramsList.size();i++){
			if((i+1) != paramsList.size()){
				sql.append("'"+paramsList.get(i)+"'").append(",");
			}else{
				sql.append("'"+paramsList.get(i)+"'");
			}
		}
		
		sql.append(")");
		
		return this.sessionFactory.getCurrentSession().createSQLQuery(sql.toString()).executeUpdate();
		
	}
	public int updateSql(String tableName,JSONObject params){
		Class<?> claz = ClassUtil.getClass(ClassUtil.getClassNameByTableName(tableName));
		Map<String, Type> feildMap = ClassUtil.getClassHeibernateType(claz.getName());
		
		Map<String, List<String>> map = parseSQLParamsAndColunm(params, false,feildMap.keySet());
		
		List<String> paramsList = map.get("paramsList");
		List<String> colunmList = map.get("colunmList");
		
		StringBuffer sql = new StringBuffer();
		sql.append("update "+tableName+" set ");
		
		for(int i = 0;i < colunmList.size();i++){
			if(!"table_id".equals(colunmList.get(i))){
				if((i+1+1) != colunmList.size()){
					sql.append(colunmList.get(i)+" = ? ").append(",");
				}else{
					sql.append(colunmList.get(i)+" = ? ");
				}
			}
		}
		
		sql.append(" where table_id = ? ");
		Query query = this.sessionFactory.getCurrentSession().createSQLQuery(sql.toString());
		
		for(int i = 0 ;i < paramsList.size();i++){
			query.setParameter(i, paramsList.get(i));
		}
		
		return query.executeUpdate();
	}
	public void deleteSql(String tableName,JSONObject params){
		StringBuffer sql = new StringBuffer();
		
		sql.append("delete from ");
		sql.append(FreemakerUtil.lowStr(tableName));
		sql.append(" where table_id = ");
		sql.append("'"+params.getString("table_id")+"'");
		
		this.sessionFactory.getCurrentSession().createSQLQuery(sql.toString()).executeUpdate();
	}
	
	private Map<String, List<String>> parseSQLParamsAndColunm(JSONObject json,boolean isAdd,Set<String> classFeild){
		Map<String, List<String>> map = new HashMap<String, List<String>>();
		List<String> paramsList = new ArrayList<String>();
		List<String> colunmList = new ArrayList<String>();
		
		String updateTableId = "";
		for(Object key:json.keySet()){
			if(classFeild.contains(key)){
				
				if(!"table_id".equals(key)){
					paramsList.add(json.getString(String.valueOf(key)));
					colunmList.add(String.valueOf(key));
				}else{
					updateTableId = json.getString("table_id");
				}

			}
		}
		if(isAdd){
			colunmList.add("table_id");
			paramsList.add(UUID.randomUUID().toString().replaceAll("-", ""));
		}else{
			colunmList.add("table_id");
			paramsList.add(updateTableId);
		}
		
		map.put("colunmList", colunmList);
		map.put("paramsList", paramsList);
		
		return map;
	}
	private SQLQuery addSQLQueryParams(Class<?> claz,SQLQuery query){
		Map<String, Type> map = ClassUtil.getClassHeibernateType(claz.getName());
		
		for(String key:map.keySet()){
			query.addScalar(key, map.get(key));
		}
			
		query.setResultTransformer(Transformers.aliasToBean(claz));
		
		return query;
	}
}
